package cn.com.oceansoft.nos.common.util;

import cn.com.oceansoft.nos.common.util.base64.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

import java.io.*;
import java.util.UUID;


/**
 * 文件操作工具类
 */
public class FileUtils {

    public static Log log = LogFactory.getLog(FileUtils.class);

    /**
     * 将输入流保存至文件
     *
     * @param is       输入流
     * @param filePath 目标文件路径
     * @return boolean
     */
    public static boolean saveFile(InputStream is, String filePath) {
        boolean rt = false;
        byte[] buffer = new byte[1024];
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(new File(filePath));
            int n = -1;
            while ((n = is.read(buffer, 0, buffer.length)) != -1) {
                fos.write(buffer, 0, n);
            }
            rt = true;
        } catch (FileNotFoundException fnfe) {
            System.out.println("fnfe:" + fnfe);
        } catch (IOException ioe) {
            System.out.println("ioe:" + ioe);
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }
        }
        return rt;
    }

    /**
     * 读取XML内容
     *
     * @param xmlFile XML文件路径
     * @return XML文件内容
     */
    public static String getXmlContent(File xmlFile) {
        try {
            Document document = new SAXReader().read(xmlFile);
            return document.asXML();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 读取文件路径
     *
     * @return 输入流内容
     */
    public static String getFileContent(String fileName) {
        BufferedReader reader = null;
        StringBuilder fileContent = new StringBuilder();
        try {
            File f = new File(fileName);
            reader = new BufferedReader(new FileReader(f));
            String line;
            while ((line = reader.readLine()) != null) {
                fileContent.append(line);
                fileContent.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return fileContent.toString();
    }

    /**
     * 读取文件内容
     *
     * @param is 转入流
     * @return 输入流内容
     */
    public static String getFileContent(InputStream is) {
        BufferedReader reader = null;
        StringBuilder fileContent = new StringBuilder();
        try {
            reader = new BufferedReader(new InputStreamReader(is));
            String line = "";
            while ((line = reader.readLine()) != null) {
                fileContent.append(line);
                fileContent.append("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return fileContent.toString();
    }

    /**
     * 向指定文件写入内容
     *
     * @param path    文件路径
     * @param content 待写入内容
     * @return boolean
     */
    public static boolean setFileContent(String path, String content) {
        boolean flag = false;
        DataOutputStream dos = null;
        try {
            if (content != null && content.length() >= 0) {
                byte abyte[] = content.getBytes();
                dos = new DataOutputStream(new FileOutputStream(path));
                dos.write(abyte, 0, abyte.length);
                dos.flush();
                flag = true;
            }
        } catch (FileNotFoundException e) {
            log.error("fnfe:" + e);
        } catch (IOException e) {
            log.error("ioe:" + e);
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

    /**
     * 文件转换为Base64编码
     *
     * @param filePath 文件路径
     * @param tmpDir   临时文件目录
     * @return Base64编码
     */
    public static String file2Base64Str(String filePath, String tmpDir) {
        File file = new File(filePath);
        String tmpFilePath = tmpDir + "/" + UUID.randomUUID().toString() + ".base64";
        File tmpFile = new File(tmpFilePath);
        StringBuilder sb = new StringBuilder();
        BufferedReader br = null;
        try {
            Base64.encode(file, tmpFile);
            // Read All Base 64 File
            br = new BufferedReader(new FileReader(tmpFile));
            String tmpStr = null;
            while ((tmpStr = br.readLine()) != null) {
                sb.append(tmpStr);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        tmpFile.delete();
        return sb.toString();
    }


    /**
     * Description: 向FTP服务器上传文件
     * @Version      1.0
     * @param url FTP服务器hostname
     * @param port  FTP服务器端口
     * @param username FTP登录账号
     * @param password  FTP登录密码
     * @param path  FTP服务器保存目录
     * @param filename  上传到FTP服务器上的文件名
     * @param input   输入流
     * @return 成功返回true，否则返回false *
     */
    public static boolean uploadFile(String url,// FTP服务器hostname
                                     int port,// FTP服务器端口
                                     String username, // FTP登录账号
                                     String password, // FTP登录密码
                                     String path, // FTP服务器保存目录
                                     String filename, // 上传到FTP服务器上的文件名
                                     InputStream input // 输入流
    ){
        boolean success = false;
        FTPClient ftp = new FTPClient();
        ftp.setControlEncoding("utf-8");
        try {
            int reply;
            ftp.connect(url, port);// 连接FTP服务器
            // 如果采用默认端口，可以使用ftp.connect(url)的方式直接连接FTP服务器
            ftp.login(username, password);// 登录
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return success;
            }

            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            ftp.enterLocalPassiveMode();
            ftp.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
            ftp.setBufferSize(100000);
            ftp.makeDirectory(path);
            ftp.changeWorkingDirectory(path);
            ftp.storeFile(filename, input);
            input.close();
            ftp.logout();
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return success;
    }

    /**
     * 获取文件扩展名
     *
     * @param fileName 文件名称
     * @return 文件扩展名
     */
    public static String getExtName(String fileName) {
        if (fileName == null)
            return "";
        String ext = "";
        int lastIndex = fileName.lastIndexOf(".");
        if (lastIndex >= 0) {
            ext = fileName.substring(lastIndex).toLowerCase();
        }
        return ext;
    }
//    /**
//     * 远程存储文件
//     *
//     * @param userName     共享授权用户名
//     * @param password     授权密码
//     * @param remoteHost   远程主机IP
//     * @param remoteFolder 远程主机共享目录
//     * @param inputStream  输入文件流
//     * @param fileName     文件名称
//     * @return String 远程文件存储路径
//     */
//    public static String smbPut(String userName, String password, String remoteHost, String remoteFolder, InputStream inputStream, String fileName) {
//        try {
//            String url = String.format("smb://%s:%s@%s/%s", userName, password, remoteHost, remoteFolder);
//            smbPut(url, inputStream, fileName);
//            return url + "/" + fileName;
//        } catch (Exception e) {
//            log.error("写入远程文件失败,失败原因：" + e.getMessage());
//            e.printStackTrace();
//        }
//        return null;
//    }
//    /**
//     * 将本地磁盘文件上传到局域网共享文件服务器指定目录下
//     *
//     * @param remoteUrl   共享电脑路径 如：smb://administrator:123456@172.17.100.139/upload
//     * @param inputStream 文件输入流
//     * @param fileName    本地路径
//     * @return String     远程存储路径
//     */
//    public static String smbPut(String remoteUrl, InputStream inputStream, String fileName) throws IOException {
//        InputStream in = null;
//        OutputStream out = null;
//        try {
//            SmbFile folder = new SmbFile(remoteUrl);
//            if (!folder.exists()) {
//                folder.mkdirs();
//            }
//            SmbFile remoteFile = new SmbFile(remoteUrl + "/" + fileName);
//            in = new BufferedInputStream(inputStream);
//            out = new BufferedOutputStream(new SmbFileOutputStream(remoteFile));
//            byte[] buffer = new byte[1024];
//            while ((in.read(buffer)) != -1) {
//                out.write(buffer);
//                buffer = new byte[1024];
//            }
//            if (log.isDebugEnabled())
//                log.debug("写入远程地址" + remoteUrl + "/" + fileName);
//            return remoteFile.getPath();
//        } finally {
//            try {
//                if (out != null) {
//                    out.close();
//                }
//                if (in != null) {
//                    in.close();
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//    }
//    /**
//     * 删除远程文件
//     *
//     * @param remoteUrl 远程共享目录文件地址
//     */
//    public static void smbDelete(String remoteUrl) {
//        try {
//            SmbFile folder = new SmbFile(remoteUrl);
//            if (folder.exists())
//                folder.delete();
//        } catch (MalformedURLException e) {
//            e.printStackTrace();
//            log.error("删除远程文件失败" + remoteUrl);
//        } catch (SmbException e) {
//            e.printStackTrace();
//            log.error("删除远程文件失败" + remoteUrl);
//        }
//    }
//    /**
//     * 远程存储文件
//     *
//     * @param userName     共享授权用户名
//     * @param password     授权密码
//     * @param remoteHost   远程主机IP
//     * @param remoteFolder 远程主机共享目录
//     * @param localDir     本地目录文件路径
//     * @return String 保存成功返回文件路径
//     */
//    public static String smbGet(String userName, String password, String remoteHost, String remoteFolder, String localDir) {
//        String url = String.format("smb://%s:%s@%s/%s", userName, password, remoteHost, remoteFolder);
//        return smbGet(url, localDir);
//    }
//    /**
//     * 从局域网中共享文件中得到文件并保存在本地磁盘上
//     *
//     * @param remoteUrl 共享电脑路径 如：smb://administrator:123456@172.16.100.139/upload/biz/12345/abc.jpg, upload为共享文件
//     *                  注：如果一直出现连接不上，有提示报错，并且错误信息是 用户名活密码错误 则修改共享机器的文件夹选项 查看 去掉共享简单文件夹的对勾即可。
//     * @param localDir  本地路径
//     * @return localFile 本地文件路径
//     */
//    public static String smbGet(String remoteUrl, String localDir) {
//        InputStream in = null;
//        OutputStream out = null;
//        try {
//            SmbFile smbFile = new SmbFile(remoteUrl);
//            String fileName = smbFile.getName();
//            File localFile = new File(localDir + File.separator + fileName);
//            in = new BufferedInputStream(new SmbFileInputStream(smbFile));
//            out = new BufferedOutputStream(new FileOutputStream(localFile));
//            byte[] buffer = new byte[1024];
//            while ((in.read(buffer)) != -1) {
//                out.write(buffer);
//                buffer = new byte[1024];
//            }
//            return localFile.getPath();
//        } catch (Exception e) {
//            log.error("获取远程文件" + remoteUrl + "失败,失败原因：" + e.getMessage());
//            e.printStackTrace();
//            return null;
//        } finally {
//            try {
//                if (out != null) {
//                    out.close();
//                }
//                if (in != null) {
//                    in.close();
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//    }

    /**
     * 创建文件目录
     *
     * @param path 目录路径
     * @return true创建目录成功 false 创建失败
     */
    public static File makeDir(String path) {
        File file = new File(path);
        if (file.exists()) {
            if (file.isDirectory()) {
                return file;
            } else {
                log.error("指定路径文件已存在,无法创建相同路径文件");
                return null;
            }
        } else {
            try {
                org.apache.commons.io.FileUtils.forceMkdir(file);
                return file;
            } catch (Exception ex) {
                log.error("创建路径" + path + "目录失败，失败原因：" + ex.getMessage());
                return null;
            }
        }
    }

    /**
     * 在指定目录下创建文件
     *
     * @param parentDir 父级目录
     * @param fileName  文件名称
     * @return File
     */
    public static File createFile(File parentDir, String fileName) {
        if (null == parentDir || !parentDir.isDirectory()) {
            makeDir(parentDir.getPath());
        }
        return new File(parentDir, fileName);
    }

    public static void createFile(InputStream inputStream, File file) throws Exception {
        org.apache.commons.io.FileUtils.copyInputStreamToFile(inputStream, file);
    }
}
